home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 3: CDPD 3
/
Almathera Ten on Ten - Disc 3: CDPD3.iso
/
fish
/
676-700
/
697
/
qmouse
/
qmouse.s
< prev
next >
Wrap
Text File
|
1995-03-18
|
28KB
|
1,434 lines
;QMouse.s
;Written by Dan Babcock
;Note: This source was assembled with Macro68. If you don't have Macro68
;(shame) it may be easily modified for other assemblers.
exeobj
objfile 'c:QMouse'
multipass
IFND _LVOSystemTagList
_LVOSystemTagList equ -$25E
ENDC
SCREENLISTSIZE equ 32 ;maximum number of screens to keep track of
POINTERLISTSIZE equ 32
HANDLERPRI equ 60 ;priority of input.device handler
MaxCopperSize equ 500
SysBackground equ $e ;Offset into gb_copinit copper list -- 2.04 only!
DefColor equ $fff ;white
move.l 4,a6
cmp.w #37,LIB_VERSION(a6)
bhs.s GoodVersion
;Print an error message - the user doesn't have 2.0
lea DosName(pc),a1
SYS OldOpenLibrary
tst.l d0
beq.s ErrEnd
move.l d0,a6
SYS Output
move.l d0,d1
moveq #EndSorry-Sorry,d3
lea Sorry(pc),a0
move.l a0,d2
SYS Write
move.l a6,a1
move.l 4,a6
SYS CloseLibrary
ErrEnd: moveq #100,d0
rts
dc.b '$VER: QMouse 2.10 (14.6.92)',$a,0
Sorry: dc.b 'Sorry, this program requires Kickstart 2.0!',$a,0
EndSorry: even
GoodVersion:
;Allocate global data structure
move.l #Data_Sizeof,d0
move.l #MEMF_CLEAR,d1
SYS AllocMem
tst.l d0
beq ErrEnd
move.l d0,a5
lea GlobalPtr(pc),a0
move.l a5,(a0)
;Allocate chip RAM data.
move.l #CData_Sizeof,d0
move.l #MEMF_CLEAR+MEMF_CHIP,d1
SYS AllocMem
move.l d0,ChipData(a5)
beq CleanUp
;Initialize static data
move.b #HANDLERPRI,InputInterrupt+LN_PRI(a5)
move.l a5,InputInterrupt+IS_DATA(a5)
moveq #1,d0
move.l d0,ClickCount(a1)
;Open libraries
lea LibTable(pc),a2
move.l a2,a3
moveq #NumLibs-1,d2
.OLibLoop:
move.w (a2)+,a1
add.l a3,a1
SYS OldOpenLibrary
move.w (a2)+,a0
add.l a5,a0
move.l d0,(a0)
beq CleanUp
dbra d2,.OLibLoop
;Parse command line
lea Template(pc),a0
move.l a0,d1
lea Options(a5),a0
move.l a0,d2
moveq #0,d3 ;no custom rdarg structure
move.l DosBase(a5),a6
SYS ReadArgs
move.l d0,ArgPtr(a5)
beq CleanUp
move.l 4,a6
;Process QUIT option, if selected.
tst.l QuitOption(a5)
beq.s .SkipQuit
lea ProcName(pc),a1
SYS FindTask
tst.l d0
beq CleanUp
move.l d0,a1
move.l TC_Userdata(a1),a0
move.l QuitSig(a0),d0
SYS Signal ;tell task to quit
bsr CleanUp
bra .Exit
.SkipQuit:
;If already installed, kill the existing process.
lea ProcName(pc),a1
SYS FindTask
tst.l d0
beq.s .NotInstalled
move.l d0,a1
move.l TC_Userdata(a1),a0
move.l QuitSig(a0),d0
SYS Signal ;tell task to quit
moveq #26,d2
.Kill: subq.l #1,d2
beq .Exit
move.l DosBase(a5),a6
moveq #2,d1
SYS Delay
lea ProcName(pc),a1
move.l 4,a6
SYS FindTask
tst.l d0
bne .Kill
.NotInstalled:
;Get stack for command.
move.l DosBase(a5),a6
SYS Cli
move.l d0,a0
move.l cli_DefaultStack(a0),d0
lsl.l #2,d0
lea CmdStackSize(pc),a0
move.l d0,(a0)
move.l 4,a6
;Copy resident part of code into allocated memory
lea StartAllocCode(pc),a0 ;source
lea ResidentCode(a5),a1 ;destination
move.l #ResidentCodeSize,d0 ;size
SYS CopyMem
SYS CacheClearU ;for 020/030/040
;Start a process
move.l DosBase(a5),a6
lea ResidentCode(a5),a0
lea EntryPoint(pc),a1
move.l a0,(a1)
lea ProcName-StartAllocCode+ResidentCode(a5),a0
lea ProcNamePtr(pc),a1
move.l a0,(a1)
lea NewProcTags(pc),a0
move.l a0,d1
SYS CreateNewProc
;Exit back to CLI
.Exit: moveq #0,d0
rts
***************************************************************************
* The following code is copied into allocated memory. *
***************************************************************************
StartAllocCode:
move.l 4,a6
move.l GlobalPtr(pc),a5
lea IntRoutine(pc),a0
move.l a0,InputInterrupt+IS_CODE(a5)
;Initialize damping constant.
move.l AccelOption(a5),d0
beq.s .NoDamp
move.l d0,a0
move.l (a0),d0
subq.l #1,d0
move.l ThreshOption(a5),d1
beq.s .DefThresh
move.l d1,a0
move.l (a0),d1
.DefThresh:
addq.l #1,d1
mulu.w d0,d1
move.w d1,DampingConstant(a5)
.NoDamp:
;Allocate signals
moveq #NumSigs-1,d2
lea Sigs(a5),a2
.SigLoop: moveq #-1,d0
SYS AllocSignal
tst.l d0
bmi CleanUp
moveq #0,d1
bset d0,d1
move.l d1,(a2)+
dbra d2,.SigLoop
;Initialize semaphore(s)
lea MySemaphore(a5),a0
SYS InitSemaphore
move.l ThisTask(a6),a0
move.l a0,Task(a5)
move.l a5,TC_Userdata(a0)
;Install no-flicker option if selected.
tst.l FlickerOption(a5)
beq.s .NoFlicker
move.l GraphBase(a5),a0
move.l gb_CopInit(a0),a0
move.l a0,OriginalCopInit(a5)
move.l ChipData(a5),a1
lea Copper(a1),a1
move.l a1,a2
move.w #MaxCopperSize/4-1,d0
.CLoop: move.l (a0)+,d1
cmp.l #$008A0000,d1
beq.s .CopEnd
move.l d1,(a1)+
dbra d0,.CLoop
clr.l FlickerOption(a5)
bra.s .NoFlicker
.CopEnd: move.l #$01800000,(a1)+
move.l #$1607FFFE,(a1)+
move.w #$0180,(a1)+
move.l #$008A0000,2(a1)
move.l a1,RealBackground(a5)
move.l a2,cop1lc+_custom
move.l GraphBase(a5),a0
move.l a2,gb_CopInit(a0)
cmp.w #color,SysBackground-2(a2)
bne.s .DefColor
move.w SysBackground(a2),(a1)
bra.s .NoFlicker
.DefColor:
move.w #DefColor,(a1)
.NoFlicker:
;Patch MANY system routines.
lea PatchTable(pc),a2
move.l a2,a3
.Patch: move.w (a2)+,d0 ;get base
beq.s .EndPatch
move.l (a5,d0.w),a1 ;library base to patch
move.w (a2)+,d0 ;get offset to new routine
lea (a3,d0.w),a0
move.l a0,d0 ;new routine address
move.w (a2)+,a0 ;_LVO offset
SYS SetFunction
move.w (a2)+,d1
move.l d0,(a5,d1.w)
bra .Patch
.EndPatch:
;Create an IORequest structure
SYS CreateMsgPort
move.l d0,InputMsgPort(a5)
beq CleanUp
move.l d0,a0
moveq #IOSTD_SIZE,d0
SYS CreateIORequest
move.l d0,InputIORequest(a5)
beq CleanUp
;Perform NoClick, if desired.
move.l NoClickOption(a5),d2
beq.s .Click
move.l d2,a0
move.l (a0),d2
.Click: moveq #0,d3
moveq #3,d4
.ClickLoop:
lea TrackName(pc),a0 ;device name
move.l d3,d0 ;unit number
move.l InputIORequest(a5),a1 ;IO request
moveq #0,d1 ;flags
SYS OpenDevice
tst.l d0
bne.s .ECLoop
move.l InputIORequest(a5),a1 ;IO request
move.l IO_UNIT(a1),a0
btst d3,d2
beq.s .SkipNoClick
bchg #TDPB_NOCLICK,TDU_PUBFLAGS(a0)
.SkipNoClick:
tst.l VerifyOption(a5)
beq.s .SkipVerify
bchg #1,TDU_PUBFLAGS(a0)
.SkipVerify:
SYS CloseDevice
.ECLoop: addq.l #1,d3
dbra d4,.ClickLoop
;Handle 'STAR' option.
tst.l StarOption(a5)
beq.s .NoStar
move.l DosBase(a5),a0
move.l dl_Root(a0),a0
bchg #0,rn_Flags(a0)
.NoStar:
;Open the input.device
lea InputName(pc),a0 ;device name
moveq #0,d0 ;unit number
move.l InputIORequest(a5),a1 ;IO request
moveq #0,d1 ;flags
SYS OpenDevice
tst.l d0
bne CleanUp
;Install input handler
move.l InputIORequest(a5),a1
move.w #IND_ADDHANDLER,IO_COMMAND(a1)
lea InputInterrupt(a5),a0
move.l a0,IO_DATA(a1)
SYS DoIO
tst.l d0
bne CleanUp
st HandlerInstalled(a5)
;Wait for signal(s)
Wait:
lea Sigs(a5),a0
move.l (a0)+,d0
moveq #NumSigs-2,d1
.. add.l (a0)+,d0
dbra d1,..
move.l 4,a6
SYS Wait
move.l d0,d1
and.l QuitSig(a5),d1
bne.s SafeCleanUp
move.l d0,d1
and.l CLISig(a5),d1
bne.s .Execute
move.l d0,d1
and.l WBenchToFrontSig(a5),d1
bne.s .WBenchToFront
;Perform ScreenToBack
move.l IntBase(a5),a6
move.l ScreenPtr(a5),d0
beq Wait
clr.l ScreenPtr(a5)
move.l d0,a0
SYS ScreenToBack
bra Wait
.WBenchToFront:
move.l IntBase(a5),a6
SYS WBenchToFront
bra Wait
.Execute:
;Execute the desired command
move.l DosBase(a5),a6
move.l CmdOption(a5),d1
beq Wait
lea .Tags(pc),a0
move.l a0,d2 ;tags
SYS SystemTagList
bra Wait
.Tags: dc.l SYS_USERSHELL,0
dc.l NP_StackSize
CmdStackSize:
dc.l 0
dc.l 0 ;end of tag list
SafeCleanUp:
;Make sure the SetFunction'ed vectors are still intact.
lea PatchTable(pc),a0
move.l a0,a2
.Safe: move.w (a0)+,d0
beq.s CleanUp
move.l (a5,d0.w),a1 ;library base
move.w (a0)+,d0
lea (a2,d0.w),a3 ;address of new routine
move.w (a0)+,d0
cmp.l 2(a1,d0.w),a3
bne Wait
addq.l #2,a0
bra .Safe
LibTable: dc.w DosName-LibTable
dc.w DosBase
dc.w IntName-LibTable
dc.w IntBase
dc.w LayersName-LibTable
dc.w LayersBase
dc.w GraphName-LibTable
dc.w GraphBase
EndLibTable:
NumLibs equ (EndLibTable-LibTable)/4
CleanUp:
;Enter with global ptr in A5
move.l 4,a6
;Remove input handler, if installed.
tst.b HandlerInstalled(a5)
beq.s .SkipHand
move.l InputIORequest(a5),a1
move.w #IND_REMHANDLER,IO_COMMAND(a1)
lea InputInterrupt(a5),a0
move.l a0,IO_DATA(a1)
SYS DoIO
.SkipHand:
tst.l OldCloseScreen(a5)
beq.s .SkipRestore
bsr RestoreMouse
bsr RestoreScreen
;Restore original vectors.
lea PatchTable(pc),a2
.RestoreVecs:
move.w (a2),d0
beq.s .SkipRestore
addq.l #4,a2 ;skip new routine info
move.l (a5,d0.w),a1 ;get library base
move.w (a2)+,a0 ;get _LVO
move.w (a2)+,d0
move.l (a5,d0.w),d0 ;old routine
SYS SetFunction
bra .RestoreVecs
.SkipRestore:
;Delay for 1/10 second to ensure that no-one is using the patch code.
move.l DosBase(a5),d0
beq.s .SkipFreeArg
move.l d0,a6
moveq #5,d1
SYS Delay
;Free argument structure
move.l ArgPtr(a5),d1
beq.s .SkipFreeArg
SYS FreeArgs
.SkipFreeArg:
move.l 4,a6
;Free signals
lea Sigs(a5),a2
moveq #NumSigs-1,d2
.SigLoop: move.l (a2)+,d1
beq.s .NextSig
moveq #-1,d0
.BitLoop: addq.l #1,d0
btst d0,d1
beq .BitLoop
SYS FreeSignal
.NextSig: dbra d2,.SigLoop
;Remove flicker option, if selected.
tst.l FlickerOption(a5)
beq.s .SkipFlicker
move.l OriginalCopInit(a5),a0
move.l GraphBase(a5),a2
move.l gb_CopInit(a2),a1
.CLoop: move.l (a1)+,(a0)+
cmp.l #$008A0000,(a0)
bne .CLoop
move.l OriginalCopInit(a5),gb_CopInit(a2)
move.l OriginalCopInit(a5),cop1lc+_custom
.SkipFlicker:
;Close libraries
lea LibTable+2(pc),a2
moveq #NumLibs-1,d2
.CLibLoop:
move.w (a2),a0
add.l a5,a0
tst.l (a0)
beq.s .SkipClose
move.l (a0),a1
SYS CloseLibrary
.SkipClose:
addq.l #4,a2
dbra d2,.CLibLoop
;Close input.device
move.l InputIORequest(a5),d0
beq.s .SkipCloseDev
move.l d0,a1
tst.b IO_ERROR(a1) ;was there an error?
bne.s .SkipCloseDev ;yes, don't close
SYS CloseDevice
.SkipCloseDev:
;Delete IORequest structure
move.l InputIORequest(a5),a0
SYS DeleteIORequest
move.l InputMsgPort(a5),a0
SYS DeleteMsgPort
;Free chip data.
move.l ChipData(a5),d0
beq.s .SkipChipData
move.l d0,a1
move.l #CData_Sizeof,d0
SYS FreeMem
.SkipChipData:
;Deallocate global structure. Note that this code is (sometimes) executed
;within the memory that we are freeing, so we are careful to terminate with
;a JMP.
move.l a5,a1
move.l #Data_Sizeof,d0
jmp _LVOFreeMem(a6)
;Semaphore routines
GetSemaphore:
movem.l a0/a6,-(sp)
move.l GlobalPtr(pc),a0
lea MySemaphore(a0),a0
move.l 4,a6
SYS ObtainSemaphore
movem.l (sp)+,a0/a6
rts
FreeSemaphore:
movem.l a0/a6,-(sp)
move.l GlobalPtr(pc),a0
lea MySemaphore(a0),a0
move.l 4,a6
SYS ReleaseSemaphore
movem.l (sp)+,a0/a6
rts
;****************** SetFunction'ed routines ***************
patch macro
dc.w \1
dc.w New\2-PatchTable
dc.w _LVO\2
dc.w Old\2
endm
PatchTable:
patch IntBase,CloseScreen
patch IntBase,CloseWindow
patch IntBase,OpenScreen
patch IntBase,ScreenToFront
patch IntBase,ScreenToBack
patch IntBase,OpenScreenTagList
patch IntBase,WBenchToFront
patch IntBase,WBenchToBack
patch IntBase,SetPointer
patch IntBase,ClearPointer
patch IntBase,DisplayBeep
patch GraphBase,LoadView
dc.w 0
NewDisplayBeep:
move.l GlobalPtr(pc),a1
tst.l BeepOption(a1)
bne.s .SkipBeep
move.l OldDisplayBeep(a1),-(sp)
.SkipBeep:
rts
NewSetPointer:
bsr GetSemaphore
movem.l d4-d5/a2-a3/a5,-(sp)
move.l GlobalPtr(pc),a5
lea PointerList(a5),a2
;Find if window is already in table and find empty spot.
moveq #POINTERLISTSIZE-1,d4
sub.l a3,a3
.WinSearch:
move.l pt_Window(a2),d5
bne.s .SkipSave
move.l a2,a3
.SkipSave:
cmp.l d5,a0
beq.s .Found
lea pt_Sizeof(a2),a2
dbra d4,.WinSearch
move.l a3,a2
move.l a2,d4
beq.s .End ;no room in table, so forget it
.Found: movem.l d0-d3/a0-a1,(a2)
.End: cmp.l MBlankWindow(a5),a0
beq.s .End1
.SkipMBlank:
movem.l (sp)+,d4-d5/a2-a3/a5
subq.l #8,sp
move.l a0,(sp)
move.l GlobalPtr(pc),a0
move.l OldSetPointer(a0),4(sp)
move.l (sp)+,a0
bsr FreeSemaphore
rts
.End1: movem.l (sp)+,d4-d5/a2-a3/a5
bsr FreeSemaphore
rts
NewClearPointer:
bsr GetSemaphore
move.l GlobalPtr(pc),a1
lea PointerList(a1),a1
moveq #POINTERLISTSIZE-1,d0
.ClearLoop:
cmp.l pt_Window(a1),a0
beq.s .Found
lea pt_Sizeof(a1),a1
dbra d0,.ClearLoop
bra.s .End
.Found: clr.l pt_Window(a1)
.End: move.l GlobalPtr(pc),a1
cmp.l MBlankWindow(a1),a0
beq.s .End1
.SkipMBlank:
move.l OldClearPointer(a1),-(sp)
.End1: bsr FreeSemaphore
rts
NewLoadView:
pea .NewLoad(pc)
move.l GlobalPtr(pc),a0
move.l OldLoadView(a0),-(sp)
rts
.NewLoad:
move.l GlobalPtr(pc),a0
tst.l FlickerOption(a0)
beq.s .End
move.l RealBackground(a0),a1
move.l GraphBase(a0),a0
move.l gb_copinit(a0),a0
move.w SysBackground(a0),(a1)
.End: rts
NewCloseScreen:
bsr GetSemaphore
move.l GlobalPtr(pc),a1
lea ScreenList(a1),a1
moveq #SCREENLISTSIZE-1,d0
.Loop: cmp.l (a1),a0
beq.s .Match
addq.l #8,a1
dbra d0,.Loop
.End: move.l GlobalPtr(pc),a1
pea RestoreWindow(pc)
move.l OldCloseScreen(a1),-(sp)
bsr FreeSemaphore
rts
.Match: clr.l (a1)
bra .End
NewCloseWindow:
bsr GetSemaphore
push a0
SYS ClearPointer
pop a0
move.l GlobalPtr(pc),a1
cmp.l MBlankWindow(a1),a0
bne.s .SkipClear
clr.l MBlankWindow(a1)
.SkipClear:
lea ScreenList+4(a1),a1
moveq #SCREENLISTSIZE-1,d0
.Loop: cmp.l (a1),a0
beq.s .Match
addq.l #8,a1
dbra d0,.Loop
.End: move.l GlobalPtr(pc),a1
move.l OldCloseWindow(a1),-(sp)
bsr FreeSemaphore
rts
.Match: clr.l -4(a1)
bra .End
MyRemember:
bsr GetSemaphore
bsr.s RememberWindow
move.l a0,-(sp)
move.l GlobalPtr(pc),a0
move.l (a0,d0.w),d0
move.l (sp)+,a0
move.l d0,-(sp)
bsr FreeSemaphore
rts
NewOpenScreen:
move.w #OldOpenScreen,d0
bra MyRemember
NewOpenScreenTagList:
move.w #OldOpenScreenTagList,d0
bra MyRemember
NewWBenchToFront:
move.w #OldWBenchToFront,d0
bsr MyRemember
bra.s RestoreWindow
NewWBenchToBack:
move.w #OldWBenchToBack,d0
bsr MyRemember
bra.s RestoreWindow
NewScreenToFront:
move.w #OldScreenToFront,d0
bsr MyRemember
bra.s RestoreWindow
NewScreenToBack:
move.w #OldScreenToBack,d0
bsr MyRemember
bra.s RestoreWindow
;****************** End of SetFunction'ed routines ***************
RememberWindow:
;This routine remembers the currently activated window on the current
;screen.
movem.l d0-d1/a0-a2/a4-a6,-(sp)
move.l GlobalPtr(pc),a5
move.l IntBase(a5),a4
move.l 4,a6
SYS Forbid
move.l ib_ActiveScreen(a4),a0
move.l ib_ActiveWindow(a4),a2
SYS Permit
;Sanity checks
move.l a0,d0
beq.s .End
move.l a2,d0
beq.s .End
lea ScreenList(a5),a1
moveq #SCREENLISTSIZE-1,d0
.ScLoop: cmp.l (a1),a0
beq.s .Match
addq.l #8,a1
dbra d0,.ScLoop
;Screen not found. Add to screen list.
lea ScreenList(a5),a1
moveq #SCREENLISTSIZE-1,d0
.AddLoop: tst.l (a1)
beq.s .Match
addq.l #8,a1
dbra d0,.AddLoop
bra.s .End ;table is full
.Match:
move.l a0,(a1)+ ;screen
move.l a2,(a1) ;currently activated window
.End: movem.l (sp)+,d0-d1/a0-a2/a4-a6
rts
RestoreWindow:
;This routine restores (re-activates) the previously activated window for
;this screen.
bsr GetSemaphore
movem.l d0-d1/a0-a1/a6,-(sp)
move.l GlobalPtr(pc),a0
lea ScreenList(a0),a1
move.l IntBase(a0),a6
move.l ib_FirstScreen(a6),a0
move.l a0,d0
beq.s .End ;sanity check
moveq #SCREENLISTSIZE-1,d0
.Loop: cmp.l (a1),a0
beq.s .Match
addq.l #8,a1
dbra d0,.Loop
move.l sc_FirstWindow(a0),a0 ;default window
move.l a0,d0
beq.s .End ;sanity check
bra.s .SkipMatch
.Match:
move.l 4(a1),a0
.SkipMatch:
SYS ActivateWindow
.End: movem.l (sp)+,d0-d1/a0-a1/a6
bsr FreeSemaphore
rts
;***************************************************************************
;Start of input handler code
;***************************************************************************
;Get window associated with current mouse position.
;Returns Window in D0 and screen in D1.
GetWindow:
movem.l d2-d4/a0-a1/a4-a6,-(sp)
move.l GlobalPtr(pc),a5
move.l LayersBase(a5),a6
move.l IntBase(a5),a4
move.l ib_FirstScreen(a4),d4
.ScLoop: tst.l d4
beq.s .ErrEnd
move.l d4,a0
move.l sc_NextScreen(a0),d4
move.w ib_MouseX(a4),d0
move.w ib_MouseY(a4),d1
move.w sc_ViewPort+vp_Modes(a0),d2
move.w d2,d3
and.w #V_LACE,d2 ;interlace?
bne.s .Lace ;yes
lsr.w #1,d1
.Lace: and.w #V_HIRES,d3 ;hires?
bne.s .Hires ;yes
lsr.w #1,d0
.Hires: sub.w sc_ViewPort+vp_DxOffset(a0),d0
bmi.s .ScLoop
sub.w sc_ViewPort+vp_DyOffset(a0),d1
bmi.s .ScLoop
push a0
lea sc_LayerInfo(a0),a0
SYS WhichLayer
pop d1
tst.l d0
beq.s .End
move.l d0,a0
move.l lr_Window(a0),d0
.End: movem.l (sp)+,d2-d4/a0-a1/a4-a6
rts
.ErrEnd: moveq #0,d0
moveq #0,d1
bra .End
DoWindowToFront:
;Perform a WindowToFront on the window in D0.
;Enter with global ptr in A1.
tst.l d0
beq.s .End1
movem.l d0-d1/a0-a1/a6,-(sp)
move.l IntBase(a1),a6
move.l d0,a0
move.l wd_WLayer(a0),a1
move.l a1,d0
beq.s .End
move.l lr_ClipRect(a1),a1
move.l a1,d0
beq.s .End
tst.l (a1)
beq.s .End
move.l wd_Flags(a0),d0
and.l #WFLG_BACKDROP,d0
bne.s .End
SYS WindowToFront
.End: movem.l (sp)+,d0-d1/a0-a1/a6
.End1: rts
BlankMouse:
movem.l d0-d3/a0-a1/a5-a6,-(sp)
move.l GlobalPtr(pc),a5
move.l IntBase(a5),a6
move.l ib_ActiveWindow(a6),d0
beq.s .End
cmp.l MBlankWindow(a5),d0
beq.s .End
move.l d0,MBlankWindow(a5)
move.l d0,a0
move.l ChipData(a5),a1
; lea ZeroMouse(a1),a1 ;not needed
moveq #1,d0 ;height
moveq #16,d1 ;width
moveq #0,d2 ;xoffset
moveq #0,d3 ;yoffset
pea .End(pc)
move.l OldSetPointer(a5),-(sp)
rts
.End: movem.l (sp)+,d0-d3/a0-a1/a5-a6
rts
RestoreMouse:
movem.l d0-d1/a0-a2/a5-a6,-(sp)
move.l GlobalPtr(pc),a5
move.l IntBase(a5),a6
move.l MBlankWindow(a5),d0
beq.s .End
;Look for window in pointer table. If present, do a SetPointer to restore
;the custom pointer. Otherwise call ClearPointer.
move.l d0,a0
clr.l MBlankWindow(a5)
lea PointerList(a5),a1
moveq #POINTERLISTSIZE-1,d0
.WinLoop: cmp.l pt_Window(a1),a0
beq.s .Found
lea pt_Sizeof(a1),a1
dbra d0,.WinLoop
pea .End(pc)
move.l OldClearPointer(a5),-(sp)
rts
.End: movem.l (sp)+,d0-d1/a0-a2/a5-a6
rts
.Found: move.l a1,a2
movem.l (a2),d0-d3/a0-a1
pea .End(pc)
move.l OldSetPointer(a5),-(sp)
rts
RestoreScreen:
push a5
move.l GlobalPtr(pc),a5
bclr #STB_SBlanked,Status(a5)
beq.s .End
move.w #DMAF_SETCLR+DMAF_COPPER+DMAF_RASTER,dmacon+_custom
.End: pop a5
rts
SigTask:
;Enter with GlobalPtr in A1 and signal in D0.
movem.l d0-d1/a0-a1/a6,-(sp)
move.l Task(a1),a1
move.l 4,a6
SYS Signal
movem.l (sp)+,d0-d1/a0-a1/a6
rts
IntRoutine:
movem.l a2/a6,-(sp)
move.l IntBase(a1),a6
bsr GetSemaphore
move.l a0,-(sp)
tst.l FlickerOption(a1)
beq.s .SkipFlick
move.l GraphBase(a1),a0
move.l gb_copinit(a0),a0
cmp.w #color,Sysbackground-2(a0)
bne.s .DefColor
move.w SysBackground(a0),d0
move.l RealBackground(a1),a0
move.w d0,(a0)
bra.s .SkipColor
.DefColor:
move.l RealBackground(a1),a0
move.w #DefColor,(a0)
.SkipColor:
move.l (sp),a0
.SkipFlick:
;Perform SunMouse
tst.l SunMouseOption(a1)
beq.s .SkipSunMouse1
cmp.b #IECLASS_RAWMOUSE,ie_Class(a0)
beq.s .SkipSunMouse1
bclr #STB_SunMouse,Status(a1)
beq.s .SkipSunMouse1
bsr GetWindow
movem.l a0-a1,-(sp)
move.l d0,a0
cmp.l ib_ActiveWindow(a6),a0
beq.s .EndSun
SYS ActivateWindow
.EndSun: movem.l (sp)+,a0-a1
.SkipSunMouse1:
move.l MBlankWindow(a1),d0
beq.s .Loop
cmp.l ib_ActiveWindow(a6),d0
beq.s .EndMBW
bsr RestoreMouse
bsr BlankMouse
.EndMBW:
.Loop: cmp.b #IECLASS_TIMER,ie_Class(a0)
beq .NotKey
;Reset screen blank
tst.l SBlankOption(a1)
beq.s .SkipSRestore
move.l ie_TimeStamp(a0),ScreenTime(a1)
bsr RestoreScreen
.SkipSRestore:
cmp.b #IECLASS_RAWKEY,ie_Class(a0)
bne .NotKey
tst.b ie_Code+1(a0)
bmi .Next ;ignore up key codes
;Do Northgate keyboard mapping.
tst.l NorthGateOption(a1)
beq.s .SkipNorthgate
lea NorthgateTable(pc),a2
move.w ie_Code(a0),d0
bclr #7,d0
.NorthgateLoop:
move.b (a2),d1
beq.s .EndNorthgate
addq.l #3,a2
cmp.b d0,d1
bne.s .NorthgateLoop
and.w #$80,ie_Code(a0)
move.b -2(a2),d0
or.b d0,ie_Code+1(a0)
move.b -1(a2),d0
bmi.s .EndNorthgate
bset d0,ie_Qualifier+1(a0)
.EndNorthgate:
.SkipNorthgate:
btst #IEQUALIFIERB_LCOMMAND,ie_Qualifier+1(a0)
bne .DoLAmiga
;Blank mouse pointer
tst.l MBlankOption(a1)
beq.s .NoMBlank
bsr BlankMouse
.NoMBlank:
bra .Next
.DoLAmiga:
cmp.w #$37,ie_Code(a0) ;'m'?
bne.s .NotM
;We found an Amiga-M. Defuse and perform action.
clr.b ie_Class(a0)
move.l ib_FirstScreen(a6),a0
move.l a0,d0
beq .EndM ;sanity check
move.l a0,ScreenPtr(a1)
move.l ScreenToBackSig(a1),d0
bsr SigTask
.EndM: bra .End
.NotM:
cmp.w #$36,ie_Code(a0) ;'n'?
bne.s .NotN
;We found an Amiga-N. Defuse and perform action.
clr.b ie_Class(a0)
move.l WBenchToFrontSig(a1),d0
bsr SigTask
bra .End
.NotN:
tst.l CmdOption(a1)
beq .Next
cmp.w #$45,ie_Code(a0) ;ESC?
bne .Next
clr.b ie_Class(a0)
move.l CLISig(a1),d0
bsr SigTask
bra .End
.NotKey:
move.w ib_MouseX(a6),d0
move.w ib_MouseY(a6),d1
cmp.b #IECLASS_RAWMOUSE,ie_Class(a0)
beq .DoMouse
cmp.w CurrentX(a1),d0
bne .DoMouse
cmp.w CurrentY(a1),d1
beq .Next
.DoMouse:
move.w d0,CurrentX(a1)
move.w d1,CurrentY(a1)
tst.l MBlankOption(a1)
beq.s .NoRestore
move.l ie_TimeStamp(a0),MouseTime(a1)
bsr RestoreMouse
.NoRestore:
;Perform SunMouse
tst.l SunMouseOption(a1)
beq.s .SkipSunMouse
move.w ie_Qualifier(a0),d0
and.w #IEQUALIFIER_LEFTBUTTON+IEQUALIFIER_RBUTTON+IEQUALIFIER_MIDBUTTON,d0
bne.s .SkipSunMouse
cmp.w #IECODE_LBUTTON+IECODE_UP_PREFIX,ie_Code(a0)
beq.s .SkipSunMouse
bset #STB_SunMouse,Status(a1)
.SkipSunMouse:
;Perform click-to-back.
tst.l CTBOption(a1)
beq.s .NoCTB
cmp.w #IECODE_RBUTTON,ie_Code(a0)
bne.s .NoCTB
move.w ie_Qualifier(a0),d0
btst #IEQUALIFIERB_LEFTBUTTON,d0
beq.s .NoCTB
movem.l d2/a0-a1,-(sp)
bsr GetWindow
tst.l d0
beq.s .FlipScreen
move.l d0,a1
move.l wd_Flags(a1),d2
and.l #WFLG_BACKDROP,d2
bne.s .FlipScreen
;Is this the only window on this screen, except for backdrop windows?
move.l wd_WScreen(a1),a1
move.l sc_FirstWindow(a1),a1
.BackLoop:
cmp.l a1,d0
beq.s .EBackLoop
move.l wd_Flags(a1),d2
and.l #WFLG_BACKDROP,d2
beq.s .FlipWindow
.EBackLoop:
move.l (a1),a1
move.l a1,d2
bne .BackLoop
.FlipScreen:
tst.l d1
beq.s .ECTB
move.l GlobalPtr(pc),a1
move.l d1,ScreenPtr(a1)
move.l ScreenToBackSig(a1),d0
bsr SigTask
bra.s .ECTB
.FlipWindow:
move.l d0,a0
SYS WindowToBack
.ECTB: movem.l (sp)+,d2/a0-a1
clr.b ie_Class(a0)
bra .Next
.NoCTB:
;Perform click-to-front.
tst.l CTFOption(a1)
beq .NoCTF
cmp.w #IECODE_LBUTTON,ie_Code(a0)
bne .NoCTF
bsr GetWindow
tst.l d0
beq .NoCTF
move.l CTFOption(a1),a2
move.l (a2),d1
cmp.l #1,d1
bhi.s .MoreThanOne
bsr DoWindowToFront
bra.s .NoCTF
.MoreThanOne:
cmp.l ClickWindow(a1),d0
beq.s .SameWindow
move.l d0,ClickWindow(a1)
moveq #1,d0
move.l d0,ClickCount(a1)
.Time: move.l ie_TimeStamp+TV_SECS(a0),ClickTime+TV_SECS(a1)
move.l ie_TimeStamp+TV_MICRO(a0),ClickTime+TV_MICRO(a1)
bra.s .NoCTF
.SameWindow:
;Check to see whether MaxClickDelay has been exceeded. If not, increment
;ClickCount and compare with (CTFOption). If equal, do a WindowToFront.
;Window under pointer in D0.
push d0
movem.l d2-d3/a0-a1,-(sp)
move.l ClickTime+TV_SECS(a1),d0
move.l ClickTime+TV_MICRO(a1),d1
move.l ie_TimeStamp+TV_SECS(a0),d2
move.l ie_TimeStamp+TV_MICRO(a0),d3
SYS DoubleClick
movem.l (sp)+,d2-d3/a0-a1
tst.l d0
beq.s .TimeExceeded
addq.l #1,ClickCount(a1)
push a0
move.l CTFOption(a1),a0
move.l (a0),d0
pop a0
cmp.l ClickCount(a1),d0
bhi.s .NeedMoreClicks
clr.l ClickCount(a1)
pop d0
bsr DoWindowToFront
bra.s .NoCTF
.TimeExceeded:
moveq #1,d0
move.l d0,ClickCount(a1)
.NeedMoreClicks:
pop d0
bra .Time
.NoCTF:
;Perform acceleration.
tst.l AccelOption(a1)
beq.s .Next
moveq #0,d0
tst.l ThreshOption(a1)
beq.s .T1
move.l ThreshOption(a1),a2
move.l (a2),d0
.T1: move.w ie_X(a0),d1
bpl.s .PosX
neg.w d1
.PosX: cmp.w d0,d1
bls.s .SkipX ;below threshold
move.l AccelOption(a1),a2
move.l (a2),d1
muls.w ie_X(a0),d1
bpl.s .SubDampX
add.w DampingConstant(a1),d1
bra.s .DampX
.SubDampX:
sub.w DampingConstant(a1),d1
.DampX: move.w d1,ie_X(a0)
.SkipX: move.w ie_Y(a0),d1
bpl.s .PosY
neg.w d1
.PosY: cmp.w d0,d1
bls.s .EndAccel
move.l AccelOption(a1),a2
move.l (a2),d1
muls.w ie_Y(a0),d1
bpl.s .SubDampY
add.w DampingConstant(a1),d1
bra.s .DampY
.SubDampY:
sub.w DampingConstant(a1),d1
.DampY: move.w d1,ie_Y(a0)
.EndAccel:
.Next: move.l a0,d1
move.l (a0),d0
move.l d0,a0
bne .Loop
;Check for time-outs (mouse and screen blanking)
move.l d1,a0
tst.l MBlankOption(a1)
beq.s .NoMTime
move.l MBlankOption(a1),a0
move.l (a0),d0 ;get value in seconds
move.l d1,a0
move.l ie_TimeStamp(a0),d1
tst.l MouseTime(a1)
beq.s .InitMBlank
sub.l MouseTime(a1),d1
cmp.l d0,d1 ;TimePassed ? UserSetting
blo.s .NoMTime
bsr BlankMouse
.NoMTime:
tst.l SBlankOption(a1)
beq.s .End
btst #STB_SBlanked,Status(a1)
bne.s .End
push a0
move.l SBlankOption(a1),a0
move.l (a0),d0 ;get value in seconds
pop a0
move.l ie_TimeStamp(a0),d1
tst.l ScreenTime(a1)
beq.s .InitSBlank
sub.l ScreenTime(a1),d1
cmp.l d0,d1 ;TimePassed ? UserSetting
blo.s .End
move.w #DMAF_COPPER+DMAF_RASTER,dmacon+_custom
clr.w color+_custom
bset #STB_SBlanked,Status(a1)
.End: move.l (sp)+,d0
bsr FreeSemaphore
movem.l (sp)+,a2/a6
rts
.InitMBlank:
move.l ie_TimeStamp(a0),MouseTime(a1)
bra .NoMTime
.InitSBlank:
move.l ie_TimeStamp(a0),ScreenTime(a1)
bra .End
GlobalPtr:
dc.l 0
NorthgateTable:
dc.b $6b,$4f,IEQUALIFIERB_LSHIFT
dc.b $6c,$4e,IEQUALIFIERB_LSHIFT
dc.b $6d,$4c,IEQUALIFIERB_LSHIFT
dc.b $6e,$4d,IEQUALIFIERB_LSHIFT
dc.b 0
ProcName: dc.b 'QMouse process',0
InputName:
dc.b 'input.device',0
TrackName:
dc.b 'trackdisk.device',0
even
EndAllocCode: ;end of code copied into allocated memory
;***********************************************************************
NewProcTags:
dc.l NP_Entry
EntryPoint:
dc.l 0
dc.l NP_Name
ProcNamePtr:
dc.l 0
dc.l NP_Cli,-1
dc.l 0 ;end of tags
Template: dc.b 'M=MBLANK/K/N,'
dc.b 'S=SBLANK/K/N,'
dc.b 'N=NOFLICKER/S,'
dc.b 'CMD/K,'
dc.b 'A=ACCELERATION/K/N,'
dc.b 'T=THRESHOLD/K/N,'
dc.b 'CTB=CLICKTOBACK/S,'
dc.b 'CTF=CLICKTOFRONT/K/N,'
dc.b 'SUNMOUSE/S,'
dc.b 'NORTHGATE/S,'
dc.b 'NOBEEP/S,'
dc.b 'NOCLICK/K/N,'
dc.b 'VERIFY/S,'
dc.b 'STAR/S,'
dc.b 'QUIT/S',0
IntName: dc.b 'intuition.library',0
GraphName:
dc.b 'graphics.library',0
DosName: dc.b 'dos.library',0
LayersName:
dc.b 'layers.library',0
;The ordering here is special: data registers first, then address
;registers, so that MOVEM may be used to save/restore the data.
STRUCTURE pt,0
LONG pt_Height
LONG pt_Width
LONG pt_XOffset
LONG pt_YOffset
LONG pt_Window
LONG pt_Pointer
LABEL pt_Sizeof
ResidentCodeSize equ EndAllocCode-StartAllocCode
STRUCTURE Data,0
WORD Nothing ;to make zero special
LONG Task
LONG InputMsgPort
LONG InputIORequest
STRUCT InputInterrupt,IS_SIZE
LONG IntBase
LONG GraphBase
LONG LayersBase
STRUCT ScreenList,SCREENLISTSIZE*8
STRUCT PointerList,POINTERLISTSIZE*pt_Sizeof
LONG OldCloseScreen
LONG OldCloseWindow
LONG OldScreenToFront
LONG OldScreenToBack
LONG OldOpenScreen
LONG OldOpenScreenTagList
LONG OldWBenchToFront
LONG OldWBenchToBack
LONG OldLoadView
LONG OldSetPointer
LONG OldClearPointer
LONG OldDisplayBeep
LONG DosBase
LONG ArgPtr
STRUCT ResidentCode,ResidentCodeSize
LONG MouseTime ;timeout for mouse blanking
LONG ScreenTime ;for screen blanking
LONG MBlankWindow
WORD DampingConstant
STRUCT MySemaphore,SS_SIZE
LONG ClickWindow
STRUCT ClickTime,TV_SIZE
LONG ClickCount
LONG Path
LONG ChipData
LONG RealBackground
LONG OriginalCopInit
LONG ScreenPtr
WORD CurrentX
WORD CurrentY
LABEL Sigs
LONG CLISig
LONG QuitSig
LONG ScreenToBackSig
LONG WBenchToFrontSig
LABEL EndSigs
LABEL Options
LONG MBlankOption
LONG SBlankOption
LONG FlickerOption
LONG CmdOption
LONG AccelOption
LONG ThreshOption
LONG CTBOption
LONG CTFOption
LONG SunMouseOption
LONG NorthGateOption
LONG BeepOption
LONG NoClickOption
LONG VerifyOption
LONG StarOption
LONG QuitOption
BYTE HandlerInstalled
BYTE Status ;various status bits (defined below)
LABEL Data_Sizeof
;Bit definitions for Status
BITDEF ST,SBlanked,0
BITDEF ST,SunMouse,1
NumSigs equ (EndSigs-Sigs)/4
STRUCTURE CData,0
STRUCT ZeroMouse,12
STRUCT Copper,MaxCopperSize+4*4
LABEL CData_Sizeof
end